home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C++ / Libraries / grayimage / read_xwd.cc < prev    next >
Encoding:
Text File  |  1994-06-30  |  11.8 KB  |  389 lines  |  [TEXT/R*ch]

  1. // This may look like C code, but it is really -*- C++ -*-
  2. /*
  3.  ************************************************************************
  4.  *
  5.  *               Grayscale Image
  6.  *
  7.  *               Read an image from the X Window dump file
  8.  *
  9.  * $Id: read_xwd.cc,v 1.4 1994/01/13 14:53:03 oleg Exp oleg $
  10.  *
  11.  ************************************************************************
  12.  */
  13.  
  14. #include "image.h"
  15. #include "endian_io.h"
  16. #include "x11wd.h"
  17.  
  18. #include <ostream.h>
  19.  
  20. /*
  21.  *------------------------------------------------------------------------
  22.  *            Create an image from the file
  23.  * This function attempt to determine the image file format by looking at
  24.  * the first two bytes of the file. They are
  25.  * 'Px' - for a Portable GrayMap
  26.  * 'MM' or 'II' - for a TIFF file
  27.  * otherwise, it _might_ be an X window dump.
  28.  * After the file format is guessed, the program calls an appropriate
  29.  * reader to actually load the file.
  30.  */
  31.  
  32. IMAGE::IMAGE(const char * file_name, const char print_header_info)
  33. {
  34.   message("\nReading the file '%s' ",file_name);
  35.   EndianIO file(file_name,ios::in);
  36.   assert( file.good() );
  37.  
  38.   char byte1 = file.peek();
  39.   if( byte1 == 'P' )
  40.     read_pgm(file,print_header_info);
  41.   else if( byte1 == 'M' || byte1 == 'I' )
  42.     read_tiff(file,print_header_info);
  43.   else
  44.     read_xwd(file,print_header_info);
  45. }
  46.  
  47. /*
  48.  *------------------------------------------------------------------------
  49.  *               Class XWDump
  50.  *     designed to contain the control info about the image
  51.  *        as defined in the X Window Dump file 
  52.  */
  53.  
  54. class XWDump            // All the info pertaining to the XWD file
  55.    : public X11WDFileHeader, public EndianIO {
  56.  
  57.  friend class IMAGE;
  58.  
  59.      void set_pixmap_type(void);    // Set the pixmap type, see below
  60.  
  61. public:
  62.      char * win_name;                  // Name of the image in the file
  63.      enum { PT_8bitGray, PT_BlackWhite, PT_General } pixmap_type;
  64.  
  65.      XWDump(EndianIO& file);            // Constructor
  66.      ~XWDump() {}                // Destructor
  67.      void info(void) const;            // Dump the header information
  68.                     // Reading the pixmap into image
  69.      void read_8bit_pixmap(GRAY& pixel_matrix, const int no_pixels);
  70.      void read_any_pixmap(IMAGE &image);    // Handle the general case
  71. };
  72.  
  73. /*
  74.  *------------------------------------------------------------------------
  75.  *            Construct the XWDump
  76.  *       by reading the header of the X Window dump file
  77.  */
  78.  
  79. XWDump::XWDump(EndianIO& file) : EndianIO(file)
  80. {
  81.  
  82.   streampos beg_of_file = EndianIO::tellg();    // Remember the curr position
  83.   set_bigendian();        // Try reading a magic byte in one order
  84.   header_size = read_long("Reading the header_size");
  85.   file_version = read_long("Reading the XWD file version");
  86.  
  87.   if( file_version != X11WD_FILE_VERSION )
  88.   {
  89.     set_littlendian();        // Try now another byte order
  90.     EndianIO::seekg(beg_of_file);
  91.     header_size = read_long("Reading the header_size");
  92.     file_version = read_long("Reading the XWD file version");
  93.   }
  94.  
  95.   assure( file_version == X11WD_FILE_VERSION,
  96.      "I have tried different byte orders but failed to read\nthe XWD "
  97.      "file version correctly" );
  98.   assure( header_size >= sizeof(X11WDFileHeader),"XWD header is too small" );
  99.  
  100.                   // Read the rest of the header
  101.   pixmap_format    = read_long("Reading the pixmap_format");
  102.   pixmap_depth     = read_long("Reading the pixmap_depth");
  103.   pixmap_width     = read_long("Reading the pixmap_width");
  104.   pixmap_height    = read_long("Reading the pixmap_height");
  105.   xoffset          = read_long("Reading the xoffset");
  106.   xbyte_order      = read_long("Reading the byte_order");
  107.   bitmap_unit      = read_long("Reading the bitmap_unit");
  108.   bitmap_bit_order = read_long("Reading the bitmap_bit_order");
  109.   bitmap_pad       = read_long("Reading the bitmap_pad");
  110.   bits_per_pixel   = read_long("Reading the bits_per_pixel");
  111.   bytes_per_line   = read_long("Reading the bytes_per_line");
  112.   visual_class     = read_long("Reading the visual_class");
  113.   red_mask         = read_long("Reading the red_mask");
  114.   green_mask       = read_long("Reading the green_mask");
  115.   blue_mask        = read_long("Reading the blue_mask");
  116.   bits_per_rgb     = read_long("Reading the bits_per_rgb");
  117.   colormap_entries = read_long("Reading the colormap_entries");
  118.   ncolors          = read_long("Reading the ncolors");
  119.   window_width     = read_long("Reading the window_width");
  120.   window_height    = read_long("Reading the window_height");
  121.   window_x         = read_long("Reading the window_x");
  122.   window_y         = read_long("Reading the window_y");
  123.   window_bdrwidth  = read_long("Reading the window_bdrwidth");
  124.  
  125.                       // Read the window name
  126.   register int len = header_size - sizeof(X11WDFileHeader);
  127.   win_name = new char[len];
  128.   if( !EndianIO::read(win_name, len) )
  129.     error("Error reading the window name");
  130.  
  131.   if( ncolors > 0 )            // Skip the Xcolors
  132.     EndianIO::seekg(ncolors*sizeof(X11XColor),ios::cur);
  133.  
  134.   set_pixmap_type();
  135. }
  136.  
  137.                 // Analyse the header and figure out if
  138.                 // we can handle the XWdump we've read.
  139.                 // Set the pixmap type.
  140. void XWDump::set_pixmap_type(void)
  141. {
  142.   const int bits_per_item = bitmap_unit;
  143.  
  144.   if( pixmap_depth > 24 )
  145.     _error("can't handle X11 pixmap_depth %d greater than 24",pixmap_depth);
  146.   if( bits_per_rgb > 24 )
  147.     _error("can't handle X11 bits_per_rgb > 24");
  148.   if( pixmap_format != ZPixmap && pixmap_depth != 1 )
  149.     _error("can't handle X11 pixmap_format %d with depth != 1",pixmap_format);
  150.   if( bits_per_item != 8 && bits_per_item != 16 && bits_per_item != 32 )
  151.     _error("X11 bitmap_unit (%d) is non-standard - can't handle",
  152.        bits_per_item);
  153.   if( bits_per_item == 8 && bits_per_pixel == 8 && 
  154.       visual_class != TrueColor && visual_class != DirectColor )
  155.     pixmap_type = PT_8bitGray;
  156.   else if( bits_per_item == 8 && bits_per_pixel == 1 )
  157.     pixmap_type = PT_BlackWhite;
  158.   else
  159.     pixmap_type = PT_General;
  160. }
  161.  
  162. /*
  163.  *------------------------------------------------------------------------
  164.  *    Print out all the control information pertaining to the
  165.  *             X Window Image read
  166.  */
  167.  
  168. void XWDump::info(void) const
  169. {
  170.   cout << "\n\n=====>The following X Window dump has been read";
  171.   cout << "\nVersion:        " << file_version;
  172.   cout << "\nPixmap format:  ";
  173.   switch(pixmap_format)
  174.   {
  175.     case XYBitmap:
  176.          cout << "XYBitmap";
  177.          break;
  178.     case XYPixmap:
  179.          cout << "XYPixmap";
  180.          break;
  181.     case ZPixmap:
  182.          cout << "ZPixmap";
  183.          break;
  184.     default:
  185.      _error("Unknown pixel format: %d",pixmap_format);
  186.   }
  187.   cout << "\nPixmap depth:   " << pixmap_depth;
  188.   cout << "\nPixmap width:   " << pixmap_width;
  189.   cout << "\nPixmap height:  " << pixmap_height;
  190.   cout << "\nBitmap x offs:  " << xoffset;
  191.   cout << "\nByte order:     " << ( xbyte_order == MSBFirst ?
  192.                     "MSBFirst" : "LSBFirst" );
  193.   cout << "\nBitmap unit:    " << bitmap_unit;
  194.   cout << "\nBitmap bitOrder:" << ( bitmap_bit_order == MSBFirst ?
  195.                   "MSBFirst" : "LSBFirst" );
  196.   cout << "\nScanline pad:   " << bitmap_pad;
  197.   cout << "\nBits per pixel: " << bits_per_pixel;
  198.   cout << "\nBytes per line: " << bytes_per_line;
  199.   cout << "\nVisual class:   ";
  200.   switch(visual_class)
  201.   {
  202.     case StaticGray:
  203.          cout << "StaticGray";
  204.          break;
  205.     case GrayScale:
  206.          cout << "GrayScale";
  207.          break;
  208.     case StaticColor:
  209.          cout << "StaticColor";
  210.          break;
  211.     case PseudoColor:
  212.          cout << "PseudoColor";
  213.          break;
  214.     case TrueColor:
  215.          cout << "TrueColor";
  216.          break;
  217.     case DirectColor:
  218.          cout << "DirectColor";
  219.          break;
  220.     default:
  221.      _error("Unknown visual class: %d",visual_class);
  222.   }
  223.  
  224.   cout << "\nZ red mask:     0x";  cout.form("%x",red_mask);
  225.   cout << "\nZ green mask:   0x";  cout.form("%x",green_mask);
  226.   cout << "\nZ blue mask:    0x";  cout.form("%x",blue_mask);
  227.   cout << "\nBits per rgb:   " << bits_per_rgb;
  228.   cout << "\nColormap items: " << colormap_entries;
  229.   cout << "\nNo. colors:     " << ncolors;
  230.   cout << "\nWindow width:   " << window_width;
  231.   cout << "\nWindow height:  " << window_height;
  232.   cout << "\nWindow left  X: " << window_x;
  233.   cout << "\nWindow upper Y: " << window_y;
  234.   cout << "\nWindow border:  " << window_bdrwidth;
  235.   cout << "\nWindow name:    " << win_name;
  236.  
  237.   cout << "\n-----End of X Window dump information\n";
  238. }
  239.  
  240. /*
  241.  *------------------------------------------------------------------------
  242.  *        Read the image pixmap and write it into the image
  243.  */
  244.  
  245.                 // Special case of the Gray scale pixelmap of
  246.                 // depth 8
  247. void XWDump::read_8bit_pixmap(GRAY& pixel_matrix, const int no_pixels)
  248. {
  249.   assert( pixmap_type == PT_8bitGray );
  250.   message("\nReading the gray scale pixel map of depth 8...");
  251.   register GRAY * pixelp;
  252.   for(pixelp = &pixel_matrix; pixelp < &pixel_matrix+no_pixels;)
  253.     *pixelp++ = read_byte("Reading the pixel map");
  254. }
  255.  
  256.                 // General case of any pixelmap
  257. void XWDump::read_any_pixmap(IMAGE& image)
  258. {
  259.   const int ncols = pixmap_width;
  260.   const int nrows = pixmap_height;
  261.   const int bits_per_item = bitmap_unit;
  262.   const int bits_per_pixel = XWDump::bits_per_pixel;
  263.   const int bit_order = bitmap_bit_order;
  264.   const int pixel_mask = ( 1 << bits_per_pixel ) - 1;
  265.   int convert_rgb = 0;
  266.   register int row;
  267.  
  268.   if( visual_class == TrueColor || visual_class == DirectColor )
  269.   {
  270.     convert_rgb = 1;
  271.     message("\nA colored image with direct RGB specification\n"
  272.         "is to be converted to gray scale\n");
  273.   }
  274.  
  275.   for(row=0; row < nrows; row++)
  276.   {
  277.     char scanline[bytes_per_line];
  278.     register int col;
  279.  
  280.     switch( bits_per_item )        // Read a scanline
  281.     {
  282.       case 8:
  283.       {
  284.     register char *p = (char *)scanline;
  285.     for(col=0; col < (signed)sizeof(scanline); col++)    
  286.       *p++ = read_byte("Reading the scanline");
  287.       }
  288.       break;
  289.  
  290.       case 16:
  291.       {
  292.     register short int *p = (short int *)scanline;
  293.     for(col=0; col < (signed)sizeof(scanline); col+=sizeof(short int))
  294.       *p++ = read_short("Reading the scanline");
  295.       }
  296.       break;
  297.  
  298.       case 32:
  299.       {
  300.     register long int *p = (long int *)scanline;
  301.     for(col=0; col < (signed)sizeof(scanline); col+=sizeof(long int))
  302.       *p++ = read_long("Reading the scanline");
  303.       }
  304.       break;
  305.  
  306.       default:
  307.          assure(0,"can't happen");
  308.     }
  309.  
  310.     register char *cp = &scanline[0];
  311.     register long int bits_storage = 0;
  312.     register int bit_shift = 0;
  313.     register int remains_bit = 0;
  314.  
  315.     for(col=0; col<ncols; col++)    // Extract pixels and put to image
  316.     {
  317.       register unsigned int pixel;
  318.       if( remains_bit == 0 )
  319.       {
  320.     switch(bits_per_item)
  321.     {
  322.       case 8:
  323.       bits_storage = *cp;
  324.       break;
  325.  
  326.       case 16:
  327.       bits_storage = *((short int *)cp);
  328.       break;
  329.  
  330.       case 32:
  331.       bits_storage = *((long int *)cp);
  332.       break;
  333.     }
  334.     cp += bits_per_item/8;
  335.     remains_bit = bits_per_item;
  336.     bit_shift = ( bit_order == MSBFirst ? bits_per_item - bits_per_pixel :
  337.               0 );
  338.       }
  339.       assert( bit_shift >= 0 );
  340.       pixel = ( bits_storage >> bit_shift ) & pixel_mask;
  341.       bit_shift += ( bit_order == MSBFirst ? - bits_per_pixel : 
  342.              bits_per_pixel );
  343.       remains_bit -= bits_per_pixel;
  344.       assure(remains_bit >= 0,"Something goes wrong with bits conversion");
  345.  
  346.       if(convert_rgb)
  347.     pixel = ((pixel & 0xff0000) << (20-16)) +    /* Red part    */
  348.             ((pixel & 0xff00) << (10-8)) +        /* Green part    */
  349.         ((pixel & 0xff));            /* Blue part    */
  350.       image(row,col) = pixel;
  351.     }
  352.     assert( cp - scanline == sizeof(scanline)/sizeof(*cp) );
  353.   }
  354. }
  355.  
  356. /*
  357.  *========================================================================
  358.  *             Root module - actual IMAGE constructor
  359.  */
  360.  
  361. void IMAGE::read_xwd(EndianIO& file, const char print_header_info)
  362. {
  363.   message("Reading the X window dump image\n");
  364.   
  365.   XWDump xwdump(file);
  366.  
  367.   if( print_header_info )
  368.     xwdump.info();
  369.  
  370.   allocate(xwdump.pixmap_height,xwdump.pixmap_width,xwdump.bits_per_pixel);
  371.  
  372.   name = xwdump.win_name;
  373.  
  374.   switch( xwdump.pixmap_type )
  375.   {                // Select the most efficient procedure
  376.     case XWDump::PT_8bitGray:
  377.          xwdump.read_8bit_pixmap(*pixels,npixels);
  378.      break;
  379.  
  380.     case XWDump::PT_BlackWhite:        // Not implemented yet
  381.     default:
  382.      xwdump.read_any_pixmap(*this);
  383.   }
  384.  
  385.   cout << form("\n%dx%dx%d image '%s' has been read\n",ncols,nrows,
  386.            bits_per_pixel,name);
  387. }
  388.  
  389.